package quadTree;

import engine.Vector;

public class BoundingBox {
	/*
	 * @ public invariant ULcorner!=null;
	 * @ public invariant LRcorner!=null;
	 */
	private /*@ spec_public @*/ Vector ULcorner, LRcorner;
	/**
	 * BoundingBox Constructor
	 * @param ULcorner the position of the upper left hand corner
	 * @param LRcorner the position of the lower left hand corner
	 */
	public BoundingBox(Vector ULcorner, Vector LRcorner){
		this.ULcorner = ULcorner;
		this.LRcorner = LRcorner;
	}
	
	public String toString() {
		return "UL: " + ULcorner.toString() + "LR: " + LRcorner.toString();
	}
	

	/**
	 * Resolves an intersection between bounding boxes
	 * @param b BoundingBox to test intersection against.
	 * @return 0 - No intersection, 1 - Intersects, 2 Contains
	 */
	/*
	 * @ requires b != null;
	 * @ ensures (int)(\result) >= 0 && (int)(\result) <= 2;
	 */
	public IntersectRes Contains(BoundingBox b){
		
		Vector[] bCor = {b.getULcorner(), b.getLRcorner()};
		Vector UL  = ULcorner;
		Vector LR  = LRcorner;
		
		if(UL.getX() < bCor[0].getX() && LR.getX() > bCor[1].getX() &&
		   UL.getY() < bCor[0].getY() && LR.getY() > bCor[1].getY()){
			return IntersectRes.contains;
		}
		else{
			for(int i = 0; i < 2; i++)
				if((UL.getX() < bCor[i].getX() && LR.getX() > bCor[i].getX()) &&
					(UL.getY() < bCor[i].getY() && LR.getY() > bCor[i].getY()))
						return IntersectRes.intersect;
		}
			
		return IntersectRes.disjoint;
	}
	
	/*
	 * Getters and setters
	 */
	/**
	 * getULcorner gets the location of the BoundingBox's upper left hand corner
	 * @return a Vector containing the coordinates of the BoundingBox's upper left hand corner
	 */
	/*
	 * @ assignable \nothing;
	 * @ ensures \result == this.ULcorner;
	 * @ returns ULcorner;
	 */
	public Vector getULcorner() {
		return new Vector(ULcorner.getX(), ULcorner.getY());
	}

	/**
	 * setULcorner sets the position of the upper left hand corner to a specified position
	 * @param uLcorner the new upper left hand corner of the BoundingBox
	 */
	/*
	 * @ assignable ULcorner;
	 * @ ensures this.ULcorner == uLcorner;
	 */
	public void setULcorner(Vector uLcorner) {
		ULcorner = new Vector(uLcorner.getX(), uLcorner.getY());
	}
	
	/**
	 * getLRcorner gets the location of the BoundingBox's lower right hand corner
	 * @return a Vector containing the coordinates of the BoundingBox's lower right hand corner
	 */
	/*
	 * @ assignable \nothing;
	 * @ ensures \result == LRcorner;
	 * @ returns LRcorner;
	 */
	public Vector getLRcorner() {
		return new Vector(LRcorner.getX(), LRcorner.getY());
	}
	/**
	 * setLRcorner sets the position of the lower right hand corner to a specified position
	 * @param uLcorner the new lower right hand corner of the BoundingBox
	 */
	/*
	 * @ assignable LRcorner;
	 * @ ensures this.LRcorner == lRcorner;
	 */
	public void setLRcorner(Vector lRcorner) {
		LRcorner = new Vector(lRcorner.getX(), lRcorner.getY());
	}
	/**
	 * getWidth Returns the height of the BoundingBox - the vertical distance between two corners 
	 * @return the height of the BoundingBox
	 */
	/*
	 * @ ensures \result = LRcorner.getX() - ULcorner.getX();
	 */
	public float getWidth(){
		return LRcorner.getX() - ULcorner.getX();
	}
	/**
	 * getHeight Returns the width of the BoundingBox - the horizontal distance between two corners
	 * @return the width of the BoundingBox
	 */
	/*
	 * @ ensures \result = LRcorner.getX() - ULcorner.getX();
	 */
	public float getHeight(){
		return LRcorner.getY() - ULcorner.getY();
	}
	/**
	 * Compares two BoundingBoxes for equality based on the location of their corners
	 * @param b the BoundingBox to be compared to
	 * @return true if the BoundingBoxes are equivalent, false if not
	 */
	/*
	 * @requires this!=null;
	 * @requires b!=null;
	 * @ensures \result = (b.getLRcorner().equals(LRcorner) && b.getULcorner().equals(ULcorner))
	 * @assignable \nothing
	 */
	public boolean equals(BoundingBox b){
		return b.getLRcorner().equals(LRcorner) && b.getULcorner().equals(ULcorner);
	}
	
	public enum IntersectRes{
		disjoint,
		intersect,
		contains
	};
}
